import 'dart:async';
import 'dart:io';

import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:audioplayers/audioplayers.dart';

import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart';

import 'package:flick_video_player/flick_video_player.dart';
import 'package:fluwx/fluwx.dart';
import 'package:sainbainu/common/apis/comment_api.dart';
import 'package:sainbainu/common/apis/common_api.dart';
import 'package:sainbainu/common/apis/content_api.dart';
import 'package:sainbainu/common/apis/user_api.dart';
import 'package:sainbainu/common/enums/resource_type.dart';
import 'package:sainbainu/common/http/exception.dart';
import 'package:sainbainu/common/models/request/comment_add_request.dart';
import 'package:sainbainu/common/models/request/pager_request.dart';
import 'package:sainbainu/common/models/request/resource_request.dart';
import 'package:sainbainu/common/models/response/comment_response.dart';
import 'package:sainbainu/common/models/response/upload_response.dart';
import 'package:sainbainu/common/repositories/comment_repository.dart';
import 'package:sainbainu/common/repositories/common_repository.dart';
import 'package:sainbainu/common/repositories/content_repository.dart';
import 'package:sainbainu/common/repositories/user_repository.dart';
import 'package:sainbainu/common/routes/routes.dart';
import 'package:sainbainu/common/services/ali_oss.dart';
import 'package:sainbainu/common/services/user.dart';
import 'package:sainbainu/common/services/wechat.dart';
import 'package:sainbainu/common/utils/compress.dart';
import 'package:sainbainu/common/utils/loading.dart';
import 'package:sainbainu/common/utils/util.dart';
import 'package:sainbainu/common/widgets/widget.dart';
import 'package:sainbainu/view/content_detail/widgets/share_menu.dart';
import 'package:scroll_to_index/scroll_to_index.dart';
import 'package:video_player/video_player.dart';
import 'package:get/get.dart';
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
import 'index.dart';

const videoUrlH = 'https://v-cdn.zjol.com.cn/276986.mp4';
const videoUrlV = 'https://v-cdn.zjol.com.cn/276993.mp4';

/// 评论区域顶部距离
double _commentAreaTop = double.infinity;

typedef UploadFn = Future<String> Function();

// 创建一个包含 Future 和标识的类
class UploadTask {
  final UploadFn future;
  final String type;

  UploadTask(this.future, this.type);
}

class ContentDetailController extends GetxController {
  ContentDetailController();

  final state = ContentDetailState();

  /// 获取评论区域高度的定时器
  Timer? _commentAreaTopTimer;

  @override
  void onInit() {
    super.onInit();

    if (Get.arguments == null) {
      Get.back();
    }

    /// 帖子ID
    state.noteId = Get.arguments['noteId'] as int;

    /// hero 动画
    state.uniqueTag = Get.arguments['uniqueTag'] as String?;
    var userAvatar = Get.arguments['avatar'] as String?;
    if (userAvatar != null && userAvatar.isNotEmpty) {
      state.userAvatar = userAvatar;
    }

    /// 滚动控制器
    state.scrollController = ScrollController();
    state.scrollController.addListener(() {
      listenScrollToggleCommentInput();
    });

    /// 观察器控制器
    state.autoScrollController = AutoScrollController();
    state.autoScrollController.addListener(() {
      listenScrollToggleCommentInput();
    });

    initAudioPlayer();

    /// 评论输入框控制器
    state.commentEditingController = TextEditingController()
      ..addListener(() {
        state.commentText = state.commentEditingController.text;
        update(['commentSubmit']);
      });

    /// 评论图上传控制器
    state.imageUploaderController = ImageUploaderController();

    /// 评论语音控制器
    state.customRecorderController = CustomRecorderController();

    /// 评论刷新控制器
    state.commentRefreshController = EasyRefreshController(
      controlFinishRefresh: false,
      controlFinishLoad: true,
    );
    state.replyCommentRefreshController = EasyRefreshController(
      controlFinishRefresh: false,
      controlFinishLoad: true,
    );
    state.commentRepository = CommentRepository(CommentApi());
    state.contentRepository = ContentRepository(ContentApi());
    state.userRepository = UserRepository(UserApi());
    state.commentPagerRequest = PagerRequest();
    state.replyCommentPagerRequest = PagerRequest();
    state.commonRepository = CommonRepository(CommonApi());

    getContentDetail();
    getCommentList().then((_) {
      // 滚动到指定评论
      var commentId = Get.arguments['commentId'] as int?;
      if (commentId != null) {
        var index = state.commentListResponse.rows
            .indexWhere((item) => item.commentId == commentId);
        if (index > -1) {
          Future.delayed(const Duration(seconds: 1)).then((_) {
            state.autoScrollController.scrollToIndex(
              index,
              preferPosition: AutoScrollPosition.middle,
            );
          });
        }
      }
    });
  }

  @override
  void onReady() {
    super.onReady();
    state.focusNode = FocusNode();
  }

  @override
  void onClose() {
    super.onClose();
    state.focusNode.dispose();
    state.flickManager?.dispose();
    state.audioPlayer?.dispose();
    _commentAreaTopTimer?.cancel();
    state.commentRefreshController.dispose();
    state.replyCommentRefreshController.dispose();
    state.autoScrollController.dispose();
  }

  /// 滚动判断评论输入框是否显示
  listenScrollToggleCommentInput() {
    bool showCommentInput =
        state.autoScrollController.offset >= _commentAreaTop;
    if (state.showCommentInput.value != showCommentInput) {
      state.showCommentInput.value = showCommentInput;
    }
  }

  /// 初始化获取评论区域距离页面顶部的距离
  initCommentAreaTop() {
    // 正文高度（44为底部图标栏高度 20为额外自行调整的值）
    double bodyHeight = MediaQuery.of(Get.context!).size.height -
        MediaQuery.of(Get.context!).padding.top -
        MediaQuery.of(Get.context!).padding.bottom -
        kToolbarHeight -
        44 -
        20;
    // 获取评论区域高度（实际需要内容区域加载完成才获取）
    getCommentAreaHeight(double bodyHeight) {
      if (state.commentInputKey.currentContext != null) {
        RenderBox renderBox = state.commentInputKey.currentContext!
            .findRenderObject() as RenderBox;
        _commentAreaTop = renderBox.size.height - bodyHeight;
      }
    }

    // 轮训获取评论区域高度
    int count = 0;
    _commentAreaTopTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
      count++;
      getCommentAreaHeight(bodyHeight);
      if (count == 6) {
        timer.cancel();
      }
    });
    getCommentAreaHeight(bodyHeight);
  }

  /// 初始化音频播放器
  initAudioPlayer() {
    state.audioPlayer = AudioPlayer();
    state.audioPlayer?.setReleaseMode(ReleaseMode.stop);
    state.audioPlayer?.onPlayerStateChanged.listen((PlayerState s) {
      bool playing = s == PlayerState.playing;
      if (state.isAudioPlaying.value != playing) {
        state.isAudioPlaying.value = playing;
      }
    });
    state.audioPlayer?.onPositionChanged.listen((Duration d) {
      int remainderSeconds = state.currentAudioMaxDuration - d.inSeconds;
      if (state.audioSeconds.value != remainderSeconds) {
        state.audioSeconds.value = remainderSeconds;
      }
    });
  }

  /// 切换播放
  bool _isToggling = false;
  Future<void> toggleAudioPlay(String url, int duration) async {
    if (_isToggling) return;
    _isToggling = true;

    // 保存当前音频时长
    state.currentAudioMaxDuration = duration;

    if (state.isAudioPlaying.value) {
      if (state.playingUrl.value == url) {
        await state.audioPlayer?.pause();
      } else {
        await state.audioPlayer?.play(UrlSource(url));
        state.playingUrl.value = url;
      }
    } else {
      if (state.playingUrl.value == url) {
        await state.audioPlayer?.resume();
      } else {
        await state.audioPlayer?.play(UrlSource(url));
        state.playingUrl.value = url;
      }
    }
    _isToggling = false;
  }

  /// 预览单张
  handlePreviewImage(String path) {
    Get.to(
      PhotoViewSaver(images: [path]),
      transition: Transition.fadeIn,
      fullscreenDialog: true,
    );
  }

  /// 预览多张
  handlePreviewImages(List list, String path) {
    int index = list.indexOf(path);
    Get.to(
      () => PhotoViewSaver(
        images: list,
        index: index,
      ),
      transition: Transition.fadeIn,
      fullscreenDialog: true,
    );
  }

  /// 内容详情
  Future<void> getContentDetail() async {
    var info = await state.contentRepository.contentDetail(state.noteId);
    state.contentInfo = info;
    update(['contentInfo']);

    // 新增浏览
    state.contentRepository.viewAdd(
      ResourceRequest(
        resourceType: ResourceType.content,
        resourceId: state.noteId,
      ),
    );

    /// 0评论时 自动展示底部评论输入框
    if (info.commentNum == null || info.commentNum == 0) {
      if (!state.showCommentInput.value) {
        state.showCommentInput.value = true;
      }
    }

    initCommentAreaTop();

    /// 视频控制器
    if (info.video != null && info.video!.isNotEmpty) {
      state.flickManager = FlickManager(
        videoPlayerController: VideoPlayerController.networkUrl(
          Uri.parse(info.video!),
        ),
        autoPlay: false,
      );
      update(['videoPlayer']);
    }
  }

  /// 获取评论列表
  Future<void> getCommentList({bool refresh = true}) async {
    if (refresh) {
      state.commentPagerRequest.pageNum = 1;
    }
    var res = await state.commentRepository.commentList(
      state.commentPagerRequest,
      state.noteId,
    );
    if (refresh) {
      state.commentListResponse.rows = res.rows;
    } else {
      state.commentListResponse.rows.addAll(res.rows);
    }
    state.commentListResponse.total = res.total;
    state.commentHasMore =
        state.commentPagerRequest.pageNum * state.commentPagerRequest.pageSize <
            res.total;
    state.commentPagerRequest.pageNum++;
    update(['commentList']);
    update(['commentTotal']);

    if (refresh) {
      state.commentRefreshController.resetFooter();
    }
  }

  /// 评论上拉下载
  Future<void> onCommentRichBottom() async {
    try {
      if (state.commentHasMore) {
        await getCommentList(refresh: false);
      }
      if (!state.commentHasMore) {
        state.commentRefreshController.finishLoad(IndicatorResult.noMore);
      } else {
        state.commentRefreshController.finishLoad(IndicatorResult.success);
      }
    } catch (e) {
      state.commentRefreshController.finishLoad(IndicatorResult.fail);
    }
  }

  /// 获取回复列表
  Future<void> getReplyCommentList({bool refresh = true}) async {
    if (refresh) {
      state.replyCommentPagerRequest.pageNum = 1;
    }
    var res = await state.commentRepository.replyCommentList(
      state.replyCommentPagerRequest,
      state.currentCommentInfo!.commentId!,
    );
    if (refresh) {
      state.replyCommentListResponse.rows = res.rows;
    } else {
      state.replyCommentListResponse.rows.addAll(res.rows);
    }
    state.replyCommentListResponse.total = res.total;
    state.replyCommentHasMore = state.replyCommentPagerRequest.pageNum *
            state.replyCommentPagerRequest.pageSize <
        res.total;
    state.replyCommentPagerRequest.pageNum++;
    update(['replyCommentList']);
    update(['replyCommentTotal']);

    if (refresh) {
      state.replyCommentRefreshController.resetFooter();
    }
  }

  /// 回复上拉下载
  Future<void> onReplyCommentRichBottom() async {
    try {
      if (state.replyCommentHasMore) {
        await getReplyCommentList(refresh: false);
      }
      if (!state.replyCommentHasMore) {
        state.replyCommentRefreshController.finishLoad(IndicatorResult.noMore);
      } else {
        state.replyCommentRefreshController.finishLoad(IndicatorResult.success);
      }
    } catch (e) {
      state.replyCommentRefreshController.finishLoad(IndicatorResult.fail);
    }
  }

  /// 当前要被回复的评论
  void setCurrentCommentInfo(CommentResponse item) {
    state.currentCommentInfo = item;
    update(['currentCommentInfo']);
    getReplyCommentList();
  }

  /// 用户详情页
  toUserDetailPage(int? customerId) {
    if (customerId == null) return;
    Get.toNamed(AppRoutes.userDetail, arguments: {'customerId': customerId});
  }

  /// 小组详情页
  toGroupDetailPage() {
    Get.toNamed(AppRoutes.groupDetail, arguments: {
      'groupId': state.contentInfo.groupId,
    });
  }

  /// 关注、取消关注
  void onFollowHandle() {
    if (state.contentInfo.customerId == null) {
      return LoadingUtil.showError('无法操作');
    }
    if (state.contentInfo.followFlag == 1) {
      state.userRepository.unFollow(state.contentInfo.customerId!);
      state.contentInfo.followFlag = 0;
    } else {
      state.userRepository.follow(state.contentInfo.customerId!);
      state.contentInfo.followFlag = 1;
    }
    update(['btn']);
  }

  /// 点赞、取消点赞
  void onGiveHandle(
    bool isGive, {
    required int resourceType,
    int? resourceId,
  }) {
    if (resourceId == null) {
      return LoadingUtil.showError('无法点赞');
    }
    var resourceRequest =
        ResourceRequest(resourceType: resourceType, resourceId: resourceId);
    if (isGive) {
      state.contentRepository.giveAdd(resourceRequest);
    } else {
      state.contentRepository.giveCancel(resourceRequest);
    }
  }

  /// 收藏、取消收藏
  void onCollectionHandle(
    bool isGive, {
    required int resourceType,
    int? resourceId,
  }) {
    if (resourceId == null) {
      return LoadingUtil.showError('无法收藏');
    }
    var resourceRequest =
        ResourceRequest(resourceType: resourceType, resourceId: resourceId);
    if (isGive) {
      state.contentRepository.collectionAdd(resourceRequest);
    } else {
      state.contentRepository.collectionCancel(resourceRequest);
    }
  }

  /// 分享到微信
  void onShareWeChat(ShareMenuType type) async {
    String? title = state.contentInfo.text;
    if (title == null || title.isEmpty) {
      title = '${state.contentInfo.customerName}的帖子';
    }
    String? thumbnail;
    if (state.contentInfo.image != null &&
        state.contentInfo.image!.isNotEmpty) {
      thumbnail = state.contentInfo.image![0];
    } else if (state.contentInfo.videoCover != null &&
        state.contentInfo.videoCover!.isNotEmpty) {
      thumbnail = state.contentInfo.videoCover;
    } else if (state.contentInfo.avatar != null &&
        state.contentInfo.avatar!.isNotEmpty) {
      thumbnail = state.contentInfo.avatar;
    }
    WeChatScene scene;
    if (type == ShareMenuType.wechatTimeline) {
      scene = WeChatScene.timeline;
    } else if (type == ShareMenuType.wechatFavorite) {
      scene = WeChatScene.favorite;
    } else {
      scene = WeChatScene.session;
    }
    await WechatService.to.shareWeb(
      'http://www.sainbainu.com',
      scene: scene,
      thumbnail: thumbnail != null ? WeChatImage.network(thumbnail) : null,
      title: title,
      description: '点赞：${state.contentInfo.giveNum ?? 0}',
    );
    state.contentRepository.shareAdd(
      ResourceRequest(
        resourceType: ResourceType.content,
        resourceId: state.noteId,
      ),
    );
    Get.back();
  }

  /// 删除评论
  void onCommentDel({int? commentId, required int resourceType}) async {
    if (commentId == null) {
      return LoadingUtil.showError('无法删除');
    }
    final OkCancelResult res = await showOkCancelAlertDialog(
      context: Get.context!,
      title: '删除提示',
      message: '确定要删除该条评论吗？',
      okLabel: '确认删除',
      cancelLabel: '取消',
      style: AdaptiveStyle.iOS,
      isDestructiveAction: true,
    );
    if (res == OkCancelResult.ok) {
      try {
        LoadingUtil.showLoading(text: '正在删除');
        await state.commentRepository.commentDel(commentId);
        LoadingUtil.showSuccess('删除成功');
        if (resourceType == ResourceType.comment) {
          getReplyCommentList();
        } else {
          getCommentList();
        }
      } on CustomHttpException catch (e) {
        LoadingUtil.showError(e.message);
      }
    }
  }

  /// 监听评论图片选择或清空
  void commentImageChange(List<AssetEntity> images) {
    state.commentImage = images.isNotEmpty ? images[0] : null;
    update(['commentSubmit']);
  }

  /// 监听录音文件或清空
  void commentAudioChange(String? path, Duration? duration) {
    state.commentAudio = path;
    state.commentAudioDuration = duration;
    update(['commentSubmit']);
  }

  /// 提交评论
  onCommentSubmit({int? resourceId, int? resourceType}) async {
    if (!UserService.to.isLogin.value) {
      Get.toNamed(AppRoutes.login);
      return;
    }
    if (UserService.to.accountInfo.value.mobileFlag == 0) {
      final OkCancelResult res = await showOkCancelAlertDialog(
        context: Get.context!,
        title: '绑定手机',
        message: '发布评论需要绑定手机号，是否绑定？',
        okLabel: '确定',
        cancelLabel: '取消',
        style: AdaptiveStyle.iOS,
      );
      if (res == OkCancelResult.ok) {
        Get.toNamed(AppRoutes.bindMobile);
      }
      return;
    }
    if (UserService.to.accountInfo.value.realFlag == 0) {
      final OkCancelResult res = await showOkCancelAlertDialog(
        context: Get.context!,
        title: '实名认证',
        message: '根据互联网法律法规要求，请先进行实名认证',
        okLabel: '确定',
        cancelLabel: '取消',
        style: AdaptiveStyle.iOS,
      );
      if (res == OkCancelResult.ok) {
        Get.toNamed(AppRoutes.realNameAuth);
      }
      return;
    }

    if (resourceId == null || resourceType == null) {
      return LoadingUtil.showInfo('无法评论');
    }
    if (state.commentText.isEmpty &&
        state.commentImage == null &&
        state.commentAudio == null) {
      return LoadingUtil.showInfo('评论不能为空');
    }

    try {
      LoadingUtil.showLoading(text: '正在评论');
      // 有媒体文件 就上传（但如果已经上传过了 就不再传了）
      if ((state.commentImage != null && state.commentImageUrl == null) ||
          (state.commentAudio != null && state.commentAudioUrl == null)) {
        await _uploadTask();
      }

      var commentAddRequest = CommentAddRequest(
        resourceType: resourceType,
        resourceId: resourceId,
        text: state.commentText,
        image: state.commentImageUrl,
        audio: state.commentAudioUrl,
        audioDuration: state.commentAudioDuration == null
            ? 0
            : state.commentAudioDuration!.inSeconds,
      );
      await state.commentRepository.commentAdd(commentAddRequest);
      LoadingUtil.showSuccess('评论成功');
      handleResetComment();
      Get.back();
      if (resourceType == ResourceType.comment) {
        getReplyCommentList();
      } else {
        getCommentList();
      }
    } on CustomHttpException catch (e) {
      LoadingUtil.showError(e.message);
    } catch (e) {
      LoadingUtil.showError(e.toString());
    }
  }

  /// 清空评论弹窗
  handleResetComment() {
    state.commentEditingController.text = '';
    state.commentText = '';
    state.commentImageUrl = null;
    state.commentAudioUrl = null;
    state.commentImage = null;
    state.commentAudio = null;
    state.commentAudioDuration = null;
    // state.imageUploaderController.clear();
    // state.customRecorderController.clear();
    update(['commentSubmit']);
  }

  /// 上传任务
  Future<void> _uploadTask() async {
    // 上传任务列表 包含图片、音频
    List<UploadTask> uploadTaskList = [];
    if (state.commentImage != null) {
      // AssetEntity 转 file 对象
      List<File> fileList = await Util.assetEntityToFiles([
        state.commentImage!,
      ]);
      // 批量压缩
      fileList = await CompressUtil().compressImages(
        CompressImagesOptions(fileList),
      );
      if (fileList.isNotEmpty) {
        uploadTaskList.add(
          UploadTask(
              () => _handleUpload(fileList[0], UploadMediaType.image), 'image'),
        );
      }
    }
    if (state.commentAudio != null) {
      var audioFile = File(state.commentAudio!);
      uploadTaskList.add(UploadTask(
        () => _handleUpload(audioFile, UploadMediaType.audio),
        'audio',
      ));
    }
    // 上传任务中取 future
    List<Future<String>> uploadFutureList =
        uploadTaskList.map((task) => task.future()).toList();

    // 统一上传
    var urls = await Future.wait<String>(uploadFutureList);
    for (int i = 0; i < urls.length; i++) {
      String url = urls[i];
      String type = uploadTaskList[i].type;

      switch (type) {
        case 'image':
          state.commentImageUrl = url;
          break;
        case 'audio':
          state.commentAudioUrl = url;
          break;
      }
    }
  }

  /// 上传
  Future<String> _handleUpload(File file, UploadMediaType mediaType) async {
    UploadResponse res = await AliOssService.to.upFile(
      file.path,
      mediaType: mediaType,
    );
    return res.url;
  }
}
